HTML Helper是用於快速產生HTML標籤與內容的工具,寫法會比直接寫HTML語法簡潔,如果靈活運用可以節省許多開發時間。HTML Helper常用方法對照表格如下:
| HTML Helper方法 | 產生的HTML | 
|---|---|
| @Html.ActionLink() | <a href="..."></a> | 
| @Html.BeginForm() | <form action="..." method="..."></form> | 
| @Html.Label() | <label></label> | 
| @Html.CheckBox() | <input type="checkbox" /> | 
| @Html.RadioButton() | <input type="radio" /> | 
| @Html.Hidden() | <input type="hidden" /> | 
| @Html.TextBox() | <input type="text" /> | 
| @Html.Password() | <input type="password" /> | 
上述這些方法如果想要增加多個HTML屬性,自然就要在方法內新增參數,有不同的多載方法可以供我們來使用。
例如下面的HTML程式碼:
<input type="text" name="id" class="form-control" required />
用HTML Helper來呈現就會變成:
@Html.TextBox("id", null, new { @class = "form-control", @required = "required" })
看起來不是很好懂,用下面的範例來說明吧~
之前的專案已經寫了很多內容有點雜了,這邊新開一個專案,專案名稱就叫HTMLHelperDemo吧~然後選擇MVC的架構建立。
我們今天一樣來寫個登入操作畫面,範例的重點放在如何用HTML Helper改寫原本HTML語法的View頁面,所以先照下面步驟完成。
HelperController的控制器,建立後Code如下:    public class HelperController : Controller
    {
        // GET: Helper
        public ActionResult Index()
        {
            return View();
        }
    }
新增 Index()方法的View,一樣照預設套用版面配置頁就好
在View添加下列HTML程式碼,使用form表單將要提交的內容包住,form提交指定的路徑是~/Helper/Login,並使用POST請求:
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<div class="container">
    <form action="~/Helper/Login" method="post">
        <div>
            <label>帳號:</label>
            <input type="text" name="id" class="form-control" required />
        </div>
        <br />
        <div>
            <label>密碼:</label>
            <input type="password" name="password" class="form-control" required />
        </div>
        <br />
        <div>
            <input type="submit" name="submit" value="登入" class="btn btn-primary" />
        </div>
    </form>
</div>
補充說明一下,帳號和密碼的欄位都有一個required的屬性,這代表在登入時會先驗證欄位是否有輸入,執行畫面如下:
Login的動作方法,且會帶入帳號和密碼的兩個參數id & password,還記得參數名稱是對應HTML標籤內的name屬性嗎?另外這裡使用ViewBag攜帶參數到登入後的View。        [HttpPost]
        public ActionResult Login(string id ,string password)
        {
            ViewBag.id = id;
            ViewBag.password = password;
            return View();
        }
Login方法的View,這裡簡單顯示登入的帳號密碼資料就好,另外增加一個可以回登入畫面的連結,Code如下:
@{
    ViewBag.Title = "Login";
}
<h2>Login</h2>
<div class="container">
    <ul>
        <li>帳號: @ViewBag.id</li>
        <li>密碼: @ViewBag.password</li>
    </ul>
    <div>
        <a href="~/Helper/Index" name="link" class="btn btn-sm btn-default">回登入畫面</a>
    </div>
</div>
到這邊都算是前幾天的教學內容,可以先執行操作看看是否能正常輸入帳密,登入後能顯示資料的畫面,按下回登入畫面連結也能回到登入畫面。如果有問題先檢視前面步驟有沒有錯誤。
接著我們來將原本View的程式碼改用HTML Helper呈現,先看到Index的View,可以改寫的部分是<form>、<label>、<input>標籤,另外在Login的View可以改寫<a>標籤。
<label>標籤這邊沒有加任何屬性所以最簡單,改寫對照如下:<label>帳號:</label>
@Html.Label("帳號")
<input>標籤改寫要看其type屬性為何,例如帳號是用type="text",則使用@Html.TextBox()方法。改寫對照如下:<input type="text" name="id" class="form-control" required />
@Html.TextBox("id", null, new { @class = "form-control", required = "required" })
這邊參數內容比較複雜,我們改寫完後移到方法上面看一下多載內容:
可以看到這個多載方法要給的參數是(name,value,htmlAttributes),name參數會同時轉換成HTML標籤的name 與 id 屬性,id屬性主要是用在套用CSS樣式與使用JavaScript語法取得元素,這邊不會深入研究;value參數代表預設值,原本的標籤沒有設定故這邊填null;htmlAttributes參數寫的方式是用new{ }將標籤的其他屬性都加進來,
屬性之間使用逗號分隔,另外因為class本身是C#關鍵字所以必須用@符號跳脫。
htmlAttributes寫法有點類似HTML語法,但沒有辦法使用Visual Studio的Intellisense輔助選取,所以這種情況是否要使用HTML Helper來寫就見仁見智了。
<form> 使用@Html.BeginForm()方法,改寫對照如下: <form action="~/Helper/Login" method="post">
     </form>
@using (Html.BeginForm("Login", "Helper", FormMethod.Post))
{
}
同樣我們看一下方法的參數內容:
要給的參數是(actionName,controllerName,method),這邊應該就很好理解,要輸入的是(動作方法名稱,控制器名稱,請求方法)。外面用了using()將HTML Helper方法包住,此用法是取代需要Html.EndForm()的寫法,如下面Code:
@{Html.BeginForm("Login", "Helper", FormMethod.Post);}
form content...
@{Html.EndForm();}
看起來麻煩多了對吧?所以完整使用@using(Html.BeginForm())的寫法就簡單囉,如果沒有加上using(),執行時會發現多了不正常的內容,有興趣可以自行測試看看~
另外補充假如@Html.BeginForm()方法不填入任何參數的話,預設使用Post傳遞變數,並且將表單傳送到與檢視同名的Action,以此例來說就會變成下列Code:
 <form action="~/Helper/Index" method="post">
     </form>
<a>標籤的改寫方式與<input>類似,這邊就不多提,使用的是@Html.ActionLink()方法,對照如下:    <div>
        <a href="~/Helper/Index" name="link" class="btn btn-sm btn-default">回登入畫面</a>
    </div>
    <div>
        @Html.ActionLink("回登入畫面", "Index", null, new { name = "link", @class = "btn btn-sm btn-default" })
    </div>
完整Code如下:
Index View
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<div class="container">
    @using (Html.BeginForm("Login", "Helper", FormMethod.Post))
    {
        <div>
            @Html.Label("帳號")
            @Html.TextBox("id", null, new { @class = "form-control", required = "required" })
        </div>
        <br />
        <div>
            @Html.Label("密碼")
            @Html.Password("password", null, new { @class = "form-control", required = "required" })
        </div>
        <br />
        <div>
            <input type="submit" name="submit" value="登入" class="btn btn-primary" />
        </div>
    }
</div>
Login View
@{
    ViewBag.Title = "Login";
}
<h2>Login</h2>
<div class="container">
    <ul>
        <li>帳號: @ViewBag.id</li>
        <li>密碼: @ViewBag.password</li>
    </ul>
    <div>
        @Html.ActionLink("回登入畫面", "Index", null, new { name = "link", @class = "btn btn-sm btn-default" })
    </div>
</div>
在輸入HTML Helper方法時,眼尖的人可能會看到有些很像的方法是以For結尾的,這些方法屬於強型別HTML Helper,寫法也不太一樣,有以下幾個重點:
@model宣告明確的型別。id與name屬性。常用的強型別方法對照表格如下:
| HTML Helper方法 | 產生的HTML | 
|---|---|
| @Html.DisplayNameFor() | 顯示物件Model屬性的名稱 | 
| @Html.DisplayFor() | 顯示物件Model屬性的資料內容 | 
| @Html.EditorFor() | 直接依照物件Model屬性產生對應 <input>欄位 | 
| @Html.LabelFor() | <label></label> | 
| @Html.CheckBoxFor() | <input type="checkbox" /> | 
| @Html.RadioButtonFor() | <input type="radio" /> | 
| @Html.HiddenFor() | <input type="hidden" /> | 
| @Html.TextBoxFor() | <input type="text" /> | 
| @Html.PasswordFor() | <input type="password" /> | 

我們用一個註冊的頁面來說明如何使用強型別Helper,首先建立一個Member類別,並新增幾個會員資料會用到的屬性,Code如下。
Model:
    public class Member
    {
        public string Id { get; set; }
        public string Password { get; set; }
        public int Age { get; set; }
        public DateTime Birthday { get; set; }
        public string Email { get; set; }
    }
接著在HelperController底下新增2個動作方法:Register()是顯示註冊填寫表單畫面,使用GET請求;另一個同名的POST方法Register(Member member)是當提交表單時,會將內容透過member物件攜帶到View。這2個動作方法皆會導向同一個View畫面,Code如下。
Controller:
        [HttpGet]
        public ActionResult Register()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Register(Member member)
        {
            return View(member);
        }
接著是重頭戲的View,在@model宣告型別為Member,這樣就可以使用強型別HTML Helper建立表單內的各個標籤內容。
@using HTMLHelperDemo.Models
@model Member
寫法是使用lambda expression的形式繫結Model的屬性,例如以下Code對照:
@Html.LabelFor(m => m.Id, "帳號")
生成HTML如下
<label for="Id">帳號</label>

這邊的m指的就是Member物件,Id屬性會對應到label標籤的for屬性,for屬性用途請參考這裡,不是本篇重點所以不多提了。
再舉例下列Code對照:
@Html.TextBoxFor(m => m.Birthday, new { @class = "form-control", type = "date" })
生成HTML如下
<input class="form-control" data-val="true" data-val-date="欄位 Birthday 必須是日期。" data-val-required="Birthday 欄位是必要項。" id="Birthday" name="Birthday" type="date" value="" />
Model的Birthday屬性對應到input標籤的id與name屬性,另外可以發現到,使用強型別Helper會針對Model屬性的型別,自動建立標籤內驗證相關的屬性。
ex: data-val="true" data-val-date="欄位 Birthday 必須是日期。" data-val-required="Birthday 欄位是必要項。"
其他內容就以此類推,完整Code如下:
View:
@using HTMLHelperDemo.Models
@model Member
@{
    ViewBag.Title = "Register";
}
<h2>Register</h2>
@using (Html.BeginForm())
{
    <div class="container">
        <div class="form-group">
            @Html.LabelFor(m => m.Id, "帳號")
            @Html.TextBoxFor(m => m.Id, new { @class = "form-control" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Password, "密碼")
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Age, "年齡")
            @Html.TextBoxFor(m => m.Age, new { @class = "form-control" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Email, "電子信箱")
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control", type = "email" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Birthday, "生日")
            @Html.TextBoxFor(m => m.Birthday, new { @class = "form-control", type = "date" })
        </div>
        <div class="form-group">
            <input type="submit" value="註冊" class="btn btn-primary" />
        </div>
    </div>
}
@if (Model != null)
{
    <hr />
    <div class="container">
        <ul>
            <li>@Html.DisplayNameFor(m => m.Id) : @Html.DisplayFor(m => m.Id)</li>
            <li>@Html.DisplayNameFor(m => m.Password) : @Html.DisplayFor(m => m.Password)</li>
            <li>@Html.DisplayNameFor(m => m.Age) : @Html.DisplayFor(m => m.Age)</li>
            <li>@Html.DisplayNameFor(m => m.Email) : @Html.DisplayFor(m => m.Email)</li>
            <li>@Html.DisplayNameFor(m => m.Birthday) : @Html.DisplayFor(m => m.Birthday)</li>
        </ul>
    </div>
}
最後面用一個if條件判定Model非null,才能顯示表單提交的內容。因為這邊使用同一個View畫面,但在一開始進入註冊頁面時,Model物件還沒有透過提交表單被建立,顯示提交內容就會有問題。
另外這邊示範了使用@Html.DisplayNameFor()與 @Html.DisplayFor()的用法,簡單來說這兩個方法分別會把Model的屬性 和 Model屬性的內容 顯示出來,不會帶任何標籤。
最後呈現結果如下:
今天利用建立簡單的登入與註冊頁面認識了HTML Helper基本的使用方式,也順便複習之前學到的內容,明天開始要進入資料庫的部分~那就明天見啦~
※小弟不才,在軟體的世界還只是個小菜雞,如果內容有任何謬誤或問題,還請各位大神前輩們多多批評指教~歡迎下方留言討論^^